{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 本地调用tool工具-使用AppBuilderEventHandler简化tool_call操作\n",
    "\n",
    "基于multi_tool_call的示例，我们可以使用Client应用来执行tool_call操作，完成指定的命令，但是需要自己配置client的思考与运行流程，较为繁琐。SDK提供了使用AppBuilderEventHandler简化tool_call操作的功能,这里我们将调用Client应用，使其调用Text2Image工具生成图片，并将文件下载到本地\n",
    "\n",
    "##### 配置运行环境&导入Client应用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import appbuilder\n",
    "\n",
    "\n",
    "# AppBuilder Token，替换为您个人的Token\n",
    "os.environ[\"APPBUILDER_TOKEN\"] = \"your api key\"\n",
    "\n",
    "# 应用为：智能问题解决者\n",
    "app_id = \"e97865e7-e1be-45d3-ab8a-ea84ca6e0b9a\"\n",
    "app_client = appbuilder.AppBuilderClient(app_id)\n",
    "conversation_id = app_client.create_conversation()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 继承AppBuilderEventHandler类实现一个Agent框架的定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from appbuilder.core.console.appbuilder_client.event_handler import AppBuilderEventHandler\n",
    "class MyEventHandler(AppBuilderEventHandler):\n",
    "    def execute_local_command(self, cmd: str):\n",
    "        import subprocess\n",
    "        try:\n",
    "            result = subprocess.check_output(cmd, shell=True).decode(\"utf-8\")\n",
    "            if result.strip() == \"\":\n",
    "                return \"命令执行成功，无返回值\"\n",
    "            return result\n",
    "        except Exception as e:\n",
    "            return str(e)\n",
    "    \n",
    "    def interrupt(self, run_context, run_response):\n",
    "        thought = run_context.current_thought\n",
    "        # 绿色打印\n",
    "        print(\"\\033[1;32m\", \"-> Agent 中间思考: \", thought, \"\\033[0m\")\n",
    "\n",
    "        tool_output = []\n",
    "        for tool_call in run_context.current_tool_calls:\n",
    "            tool_call_id = tool_call.id\n",
    "            tool_res = self.execute_local_command(\n",
    "                **tool_call.function.arguments)\n",
    "            # 蓝色打印\n",
    "            print(\"\\033[1;34m\", \"-> 本地ToolCall结果: \\n\", tool_res, \"\\033[0m\\n\")\n",
    "            tool_output.append(\n",
    "                {\n",
    "                    \"tool_call_id\": tool_call_id,\n",
    "                    \"output\": tool_res\n",
    "                }\n",
    "            )\n",
    "        return tool_output\n",
    "    \n",
    "    def success(self, run_context, run_response):\n",
    "        print(\"\\n\\033[1;31m\",\"-> Agent 非流式回答: \\n\", run_response.answer, \"\\033[0m\")\n",
    "\n",
    "    def running(self, run_context, run_response):\n",
    "        print(\"\\n\\033[1;31m\",\"-> Agent 流式回答: \\n\", run_response.answer, \"\\033[0m\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 定义本地的tools工具"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [\n",
    "    {\n",
    "        \"type\": \"function\",\n",
    "        \"function\": {\n",
    "            \"name\": \"execute_local_command\",\n",
    "            \"description\": \"可以在bash环境中，执行输入的指令, 注意，一次只能执行一个完整的原子命令。并且下载文件使用curl命令，因为没有安装wget，例如：ls\",\n",
    "            \"parameters\": {\n",
    "                \"type\": \"object\",\n",
    "                \"properties\": {\n",
    "                    \"cmd\": {\n",
    "                        \"type\": \"string\",\n",
    "                        \"description\": \"需要执行的指令\",\n",
    "                    },\n",
    "                },\n",
    "                \"required\": [\"cmd\"],\n",
    "            },\n",
    "        },\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 运行Client实现实现链路的调用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with app_client.run_with_handler(\n",
    "        conversation_id = conversation_id,\n",
    "        query = \"请为我生成一张男生头像照片，并下载到本地\",\n",
    "        tools = tools,\n",
    "        event_handler = MyEventHandler(),\n",
    "    ) as run:\n",
    "        run.until_done()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Agent运行流程及输出\n",
    "  \n",
    "![Agent运行流程及输出](https://bj.bcebos.com/v1/appbuilder-sdk-components/Agent%E8%BF%90%E8%A1%8C%E6%B5%81%E7%A8%8B.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-08-22T08%3A38%3A58Z%2F-1%2Fhost%2F25e5b0ac328376a048c919d16c8d6fab9044d09ea2bb4b8b7614b958bb40182f)\n",
    "\n",
    "- 查看下载至本地的图片\n",
    "\n",
    "![载至本地的图片](https://bj.bcebos.com/v1/appbuilder-sdk-components/boy_avatar.png?authorization=bce-auth-v1%2FALTAKGa8m4qCUasgoljdEDAzLm%2F2024-08-22T08%3A40%3A26Z%2F-1%2Fhost%2F5d6f2f482bc72b487f59f7bee18e68aacf0399b71210e11a16e99f59754c64c6)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python-12",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
